package element.synt;

import element.base.Synt;
import element.base.TreeNode;
import intermediate_representation.AssignRP;
import intermediate_representation.DefineRP;
import symbal.Symbal;
import symbal.Vtype;
import symbal.constsymbal.ConstInt;
import symbal.constsymbal.ConstInt1;
import symbal.constsymbal.ConstInt2;
import symbal.constsymbal.ConstSymbal;
import table.InterCodeTable;

import java.util.ArrayList;

//VarDecl → BType VarDef { ',' VarDef } ';'
//VarDef → Ident { '[' ConstExp ']' } | Ident { '[' ConstExp ']' } '=' InitVal
public class VarDecl extends Synt {
    @Override
    public void tointerRP() {
        ArrayList<TreeNode> nodes = this.getNodes();
        int loop = (nodes.size() - 1) / 2;
        for (int i = 0; i < loop; i++) {
            int index = 2 * i + 1;
            VarDef varDef = (VarDef) nodes.get(index);
            String name = varDef.findFirst().getContent();
            ArrayList<TreeNode> defnodes = varDef.getNodes();
            int subloop = 0;
            boolean asg = false;
            if (defnodes.get(defnodes.size() - 1) instanceof InitVal) {
                subloop = (defnodes.size() - 3) / 3;
                asg = true;
            } else {
                subloop = (defnodes.size() - 1) / 3;
                asg = false;
            }
            if (subloop == 0) {
                Symbal symbal = new Symbal(name, Vtype.INT);
                String mipsname = "var" + InterCodeTable.varnum;
                symbal.setMipsName(mipsname);
                InterCodeTable.varnum++;
                InterCodeTable.symbalTable.addSymbal(symbal);

                DefineRP defineRP = new DefineRP(false, mipsname);
                InterCodeTable.addCode(defineRP);

                if (asg) {
                    int nowindex = InterCodeTable.regindex;
                    InitVal initVal = (InitVal) defnodes.get(2);
                    if (InterCodeTable.global) {
                        String value0 = initVal.globalgetvalue0();
                        AssignRP assignRP = new AssignRP(mipsname, value0);
                        InterCodeTable.addCode(assignRP);
                        ConstSymbal constSymbal = new ConstInt(name, Integer.parseInt(value0));
                        InterCodeTable.globalTable.addSymbal(constSymbal);
                    } else {
                        Exp value0 = initVal.getvalue0();
                        value0.tointerRP();
                        String tmp = InterCodeTable.nowVar;
                        if (tmp.charAt(0) == '$') {
                            InterCodeTable.setLastName(mipsname);
                        } else {
                            AssignRP assignRP = new AssignRP(mipsname, tmp);
                            InterCodeTable.addCode(assignRP);
                        }
                        InterCodeTable.regindex = nowindex;
                    }
                }
            } else if (subloop == 1) {
                ConstExp len1exp = (ConstExp) defnodes.get(2);
                int len1 = len1exp.calcu();
                Symbal symbal = new Symbal(name, Vtype.INT1);
                symbal.setLen1(len1);
                String mipsname = "var" + InterCodeTable.varnum;
                symbal.setMipsName(mipsname);
                InterCodeTable.varnum++;
                InterCodeTable.symbalTable.addSymbal(symbal);

                DefineRP defineRP = new DefineRP(false, mipsname, len1);
                InterCodeTable.addCode(defineRP);

                if (asg) {
                    InitVal initVal = (InitVal) defnodes.get(5);
                    if (InterCodeTable.global) {
                        ArrayList<String> value1 = initVal.globalgetvalue1(len1);
                        for (int j = 0; j < len1; j++) {
                            String unit = mipsname + "[" + j + "]";
                            AssignRP assignRP = new AssignRP(unit, value1.get(j));
                            InterCodeTable.addCode(assignRP);
                        }
                        ConstSymbal constSymbal = new ConstInt1(name, value1);
                        InterCodeTable.globalTable.addSymbal(constSymbal);
                    } else {
                        ArrayList<Exp> value1 = initVal.getvalue1(len1);
                        for (int j = 0; j < len1; j++) {
                            String unit = mipsname + "[" + j + "]";
                            int nowindex = InterCodeTable.regindex;
                            value1.get(j).tointerRP();
                            String tmp = InterCodeTable.nowVar;
                            if (tmp.charAt(0) == '$' && !unit.contains("[")) {
                                InterCodeTable.setLastName(unit);
                            } else {
                                AssignRP assignRP = new AssignRP(unit, tmp);
                                InterCodeTable.addCode(assignRP);
                            }
                            InterCodeTable.regindex = nowindex;
                        }
                    }
                }
            } else if (subloop == 2) {
                ConstExp len1exp = (ConstExp) defnodes.get(2);
                ConstExp len2exp = (ConstExp) defnodes.get(5);
                int len1 = len1exp.calcu();
                int len2 = len2exp.calcu();
                Symbal symbal = new Symbal(name, Vtype.INT2);
                symbal.setLen1(len1);
                symbal.setLen2(len2);
                String mipsname = "var" + InterCodeTable.varnum;
                symbal.setMipsName(mipsname);
                InterCodeTable.varnum++;
                InterCodeTable.symbalTable.addSymbal(symbal);

                DefineRP defineRP = new DefineRP(false, mipsname, len1, len2);
                InterCodeTable.addCode(defineRP);

                if (asg) {
                    InitVal initVal = (InitVal) defnodes.get(8);
                    if (InterCodeTable.global) {
                        ArrayList<ArrayList<String>> value2 = initVal.globalgetvalue2(len1, len2);
                        for (int j = 0; j < len1; j++) {
                            for (int k = 0; k < len2; k++) {
                                int point = j * len2 + k;
                                String unit = mipsname + "[" + point + "]";
                                AssignRP assignRP = new AssignRP(unit, value2.get(j).get(k));
                                InterCodeTable.addCode(assignRP);
                            }
                        }
                        ConstSymbal constSymbal = new ConstInt2(name, value2);
                        InterCodeTable.globalTable.addSymbal(constSymbal);
                    } else {
                        ArrayList<ArrayList<Exp>> value2 = initVal.getvalue2(len1, len2);
                        for (int j = 0; j < len1; j++) {
                            for (int k = 0; k < len2; k++) {
                                int point = j * len2 + k;
                                String unit = mipsname + "[" + point + "]";
                                int nowindex = InterCodeTable.regindex;
                                value2.get(j).get(k).tointerRP();
                                String tmp = InterCodeTable.nowVar;
                                if (tmp.charAt(0) == '$' && !unit.contains("[")) {
                                    InterCodeTable.setLastName(unit);
                                } else {
                                    AssignRP assignRP = new AssignRP(unit, tmp);
                                    InterCodeTable.addCode(assignRP);
                                }
                                InterCodeTable.regindex = nowindex;
                            }
                        }
                    }
                }
            }
        }
    }
}
